啊,十天後,我們來到了書的第70頁(整本書有455頁),其實進度有點緩慢Orz不過還是秉持著第8天的小語:
『Keep moving forward. One step at a time.』,不急,只要我繼續往前進,一次一步慢慢扎穩就好!
好的,來談談Ruby中非常重要的一環:雜湊(Hash)。
※什麼是雜湊?(p.70)
『雜湊(Hash)是一種資料結構,其中保存了一組稱為鍵(key)的物件,而且每個鍵都會被關聯到一個值(value)。雜湊也被稱為對映表,因為它會將鍵對應至值。雜湊有時會被稱為關聯陣列(associative array),因為每個鍵都會被關聯到一個值,所以可將它視為以任何物件(而非整數)為索引值的陣列。』
上面的文字完全來自於書本中,雖然讀起來有點跳針XD,但你不得不說,重要的事情會被說三次,你看到上面這段什麼東西出現三次了嗎XD?
『每個鍵都會被關聯到一個值』!!!
『因為它會將鍵對應至值』!!!
『因為每個鍵都會被關聯到一個值』!!!
是的!不管你要叫它什麼名字,它有一個特大重點:在雜湊中,有一個鍵(key)會對到一個值(value)!
馬上來看個例子:
rank = { "非常喜歡" => 5, "很喜歡" => 4, "沒感覺" => 3, "很討厭" => 2, "非常討厭" =>1 }
上面這個雜湊是以大括號 { } 包起來,其中,鍵(key)指的是"非常喜歡"、"很喜歡"、"沒感覺"、"很討厭"、"非常討厭",而值(value)指的是5、4、3、2、1。
以下三種寫法都是雜湊的寫法:
rank1 = { "非常喜歡" => 5, "很喜歡" => 4, "沒感覺" => 3, "很討厭" => 2, "非常討厭" =>1 }
rank2 = { :非常喜歡 => 5, :很喜歡 => 4, :沒感覺 => 3, :很討厭 => 2, :非常討厭 =>1 }
rank3 = { 非常喜歡: 5, 很喜歡: 4, 沒感覺: 3, 很討厭: 2, 非常討厭: 1 }
把上面這三行拿去irb執行後可以看到:
rank1:
=> {"非常喜歡"=>5, "很喜歡"=>4, "沒感覺"=>3, "很討厭"=>2, "非常討厭"=>1}
rank2:
=> {:非常喜歡=>5, :很喜歡=>4, :沒感覺=>3, :很討厭=>2, :非常討厭=>1}
rank3:
=> {:非常喜歡=>5, :很喜歡=>4, :沒感覺=>3, :很討厭=>2, :非常討厭=>1}
有注意到嗎?其實rank2與rank3執行結果是完全相同的!rank3的寫法是ruby1.9之後才支援的寫法,這種寫法比較簡潔方便。但更要注意的是, "非常喜歡" 和 :非常喜歡 是完全不同的兩種key喔!以下來證明兩種完全不同(數學老師上身):
#如果我們想把rank2中的:非常喜歡的值從5改成100,我們可以這樣寫:
rank2[:非常喜歡] = 100
#此時rank2變成:
=> {:非常喜歡=>100, :很喜歡=>4, :沒感覺=>3, :很討厭=>2, :非常討厭=>1}
#但如果我的改法是這樣寫:
rank2["非常喜歡"] = 555
#此時rank2變成:
=> {:非常喜歡=>100, :很喜歡=>4, :沒感覺=>3, :很討厭=>2, :非常討厭=>1, "非常喜歡"=>555}
如果它找得到相同的key,會直接改掉原本key的值,但是因為他找不到相同的key,所以就在最後面新增了一組key和value。
由上述可知"非常喜歡"與:非常喜歡是完全不同的兩種key,得證XD!
事實上,如果你要比較兩個雜湊的鍵到底有沒有一樣,也可以使用 .eql? 這個方法,例如:
a = {:love =>5, :hate =>0} => {:love=>5, :hate=>0}
b = {"love" =>5, "hate" =>0} => {"love"=>5, "hate"=>0}
a.eql?b => false
再次證明這是不一樣的雜湊喔!
其實有個更重要的議題是,字串 " " 跟符號 : 的差異是什麼?好像不太能用一兩句話說清楚,這個書中在本章節最後面有提,到時候會一併說明!
=================================================
第十一天,
Believe in yourself.
加油!
"hello" => 這是 string
:hello => 這是 symbol
兩者之間的差異在於:
在 Ruby 當中每一個 string 都是存放在不同的記憶體位置,即使內容完全一樣也是。例如:
"hello".object_id
=> 70248908847880
"hello".object_id
=> 70248908816100
(兩者的 object id 不同,意味著兩個 string 分別置於不同的記憶體位址)
然而當你在 Ruby 宣告一個 symbol 時,一個 symbol 只會占用一個記憶體位址,也就是說兩個一樣的 symbol ,記憶體位址都是一樣的,不會浪費額外空間存一樣的東西。
因此如果你在 irb 測試就會看到類似以下的結果:
2.0.0-p353 :003 > :hello.object_id
=> 538888
2.0.0-p353 :004 > :hello.object_id
=> 538888
@Kevin謝謝你的補充解釋!而且講得超清楚!!感謝感謝!!!
我也要把書上提到相關的部分補充上來,雖然Ruby支援字串(string)跟符號(symbol)都能當做Key,但由於字串是可變動的,一旦key被改變時,連帶他在記憶體的位置(書上指的是雜湊碼)也會被改變,導致存放雜湊的雜湊表會遭到破壞。因此較建議以symbol(在記憶體的位置為唯一)作為雜湊的key,才能正確運作。
補充一點點「資料結構」的概念:
不管是哪一個程式語言,一定都有 array (陣列),事實上 array 就是一種 Data Sructure 。Array 以 low level 的角度來看,實際上它就是連續的記憶體位址。
array 雖然方便,但是在某些情境下事實上使用 array 是不太適合的,例如:你有大量資料,而這些資料是存在一個 array 裡面,那麼假設我們要在 array[3] 的位置新增一筆資料,就必須要把「原來 array[3]的值」以及「其後面所有的元素」都往後挪一格,很明顯這樣的效能是非常低落的。
因此如果想要程式的效能很好,除了演算法要選對,資料結構也是非常重要的因素。
在 Ruby 裡面已經內建 Hash 這種 Data Structure ,因此開發者可以輕易地使用。不過如果換成 C 這種較 low level 的程式語言,這些東西就得自己實作了。
基本上寫 Web 不太會用到這些東西啦 XD 但是我覺得這是非常重要的概念,所以特別補充一下。
(y) Hash真是太方便了!
深深覺得自己對程式的語言還有很大的不足,所以在解釋時都不能說明的很清楚XD",從Kevin的文章中總是能得到很多幫助啊!都是扎實而且非常清楚的!!哈哈即使這些可能用不到,但卻是很重要的觀念呢!謝謝Kevin!!